//! # Card
//!
//! 定义卡牌类型
//!
//! 这也是 sgs_core 的核心类型之一
//!
//! 其他包应该引入此类型

use super::{color::Color, kind::Kind, point::Point};

/// # Card
///
/// 基本类型：卡牌
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Card {
    /// 卡牌花色
    pub color: Color,

    /// 卡牌点数
    pub point: Point,

    /// 卡牌类型
    pub kind: Kind,

    /// 卡牌名称
    pub name: String,
}

impl std::fmt::Display for Card {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}{} {} {}",
            self.color, self.point, self.name, self.kind
        )
    }
}

impl TryFrom<(&str, &str)> for Card {
    type Error = crate::Error;

    /// 从字符串解析出 Card 结构体
    ///
    /// 输入 text 应该为例如 `杀/红桃/10/基本` 模式
    ///
    /// 解析失败会返回错误
    ///
    /// 可以设置第二个参数作为分隔符
    ///
    fn try_from(value: (&str, &str)) -> Result<Self, Self::Error> {
        let mut card = Card::default();

        for (index, text) in value.0.split(value.1).enumerate() {
            match index {
                0 => card.name = text.to_owned(),
                1 => card.color = Color::try_from(text)?,
                2 => card.point = Point::try_from(text)?,
                3 => card.kind = Kind::try_from(text)?,
                _ => break,
            }
        }

        Ok(card)
    }
}

impl TryFrom<&str> for Card {
    type Error = crate::Error;

    /// 从字符串解析出 Card 结构体
    ///
    /// 输入 text 应该为例如 `杀/红桃/10/基本` 模式
    ///
    /// 解析失败会返回错误
    ///
    /// 默认分隔符为 "/"
    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Self::try_from((value, "/"))
    }
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_try_from_str() {
        let want = Card {
            color: Color::Heart,
            point: Point::P10,
            kind: Kind::Basic,
            name: "杀".to_owned(),
        };

        let get = Card::try_from("杀/红桃/10/基本").unwrap();

        assert_eq!(want, get);
        assert!(Card::try_from("杀/红桃/?").is_err());
        assert!(Card::try_from("杀/红桃/10").is_ok());
        assert!(Card::try_from("杀/红桃/10/基本////").is_ok());
    }
}
